package com.kc.gb.device.common.utils;

import cn.hutool.core.util.StrUtil;
import com.kc.gb.device.common.dto.I18NException;
import com.kc.gb.device.common.enums.ErrorCode;
import lombok.Data;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.HibernateValidatorConfiguration;

import javax.validation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;

/**
 * @author : evan.liu
 * @version V1.0
 * @Description: 对象验证工具类
 * @date Date : 2022年04月03日 8:08 下午
 */

public class Validators {

    public static void main(String[] args) {
        Student student = new Student();
        student.setName("");

        Teacher teacher = new Teacher();
        teacher.setName("liuwei");
        teacher.setStudent(student);
        validate(teacher);
    }

    @Data
    public static class Teacher{
        @NotEmpty(message = "名称不允许为空")
        private String name;

        @Valid // 标识嵌套校验
        @NotNull(message = "student 属性不允许为空")
        private Student student;
    }

    @Data
    public static class Student{
        @NotEmpty(message = "名称不允许为空")
        private String name;
    }

    /**
     * 根据默认框架验证参数的有效性(默认一般为HibernateValidate)
     * @param obj
     * @param <T>
     */
    public static<T> void validate(T obj) throws IllegalArgumentException{
        if(ObjectUtils.isEmpty(obj)){
            return;
        }
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        Set<ConstraintViolation<T>> validateResult = validator.validate(obj);
        if(validateResult==null || validateResult.size()==0) {
            return;
        }
        List<String> msg = validateResult.stream().map(x->{
            String notice = "";
            String template = x.getMessageTemplate();
            if(!template.isEmpty() && template.startsWith(StringPool.LEFT_BRACE) && template.endsWith(StringPool.RIGHT_BRACE)){
                notice = x.getPropertyPath() + StringPool.SPACE +x.getMessage();
            }else{
                notice = x.getMessageTemplate();
            }
            return notice;
        }).collect(Collectors.toList());
        throw new ValidationException(String.join(StringPool.SEMICOLON,msg));
    }

    /**
     * 校验这个Bean上 某个具体的属性
     * @param obj
     * @param <T>
     * @param <R>
     */
    public static<T,R> void validateProperty(T obj, String propertyName){
        if(ObjectUtils.isEmpty(obj)){
            return;
        }
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        Set<ConstraintViolation<T>> validateResult = validator.validateProperty(obj,propertyName);
        if(validateResult==null || validateResult.size()==0) {
            return;
        }
        List<String> msg = validateResult.stream().map(x->{
            String notice = "";
            String template = x.getMessageTemplate();
            if(!template.isEmpty() && template.startsWith(StringPool.LEFT_BRACE) && template.endsWith(StringPool.RIGHT_BRACE)){
                notice = x.getPropertyPath() + StringPool.SPACE +x.getMessage();
            }else{
                notice = x.getMessageTemplate();
            }
            return notice;
        }).collect(Collectors.toList());
        throw new ValidationException(String.join(StringPool.SEMICOLON,msg));
    }

    /**
     * 指定HibernateValidate框架验证参数的有效性
     * @param obj
     * @param <T>
     */
    public static<T> void doHibernateValidation(T obj){
        if(ObjectUtils.isEmpty(obj)){
            return;
        }
        HibernateValidatorConfiguration configure = Validation.byProvider(HibernateValidator.class).configure();
        ValidatorFactory validatorFactory = configure.failFast(false).buildValidatorFactory();
        // 根据validatorFactory拿到一个Validator
        Validator validator = validatorFactory.getValidator();
        // 使用validator对结果进行校验
        Set<ConstraintViolation<T>> validateResult = validator.validate(obj);
        if(validateResult==null || validateResult.size()==0) {
            return;
        }
        List<String> msg = validateResult.stream().map(x->{
            String notice = "";
            String template = x.getMessageTemplate();
            if(!template.isEmpty() && template.startsWith(StringPool.LEFT_BRACE) && template.endsWith(StringPool.RIGHT_BRACE)){
                notice = x.getPropertyPath() + StringPool.SPACE +x.getMessage();
            }else{
                notice = x.getMessageTemplate();
            }
            return notice;
        }).collect(Collectors.toList());
        throw new ValidationException(String.join(StringPool.SEMICOLON,msg));
    }

    public static boolean isSqlParameterLegal(String value){
        if(StringUtils.isEmpty(value)){
            return true;
        }
        String filtered = filterString(value);
        if(!StringUtils.equalsAnyIgnoreCase(value,filtered)){
            throw new ValidationException(StrUtil.format("Illegal sql parameter :{}",value));
        }
        return true;
    }

    /**
     * 清除掉所有特殊字符 (保留.)
     * @param str
     * @return
     * @throws PatternSyntaxException
     */
    public static String filterString(String str) throws PatternSyntaxException {
        if(StringUtils.isEmpty(str)){
            return str;
        }
        // 只允许字母和数字 // String regEx ="[^a-zA-Z0-9]";
        //String regEx="[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        String regEx="[`~!@#$%^&*()+=|{}':;',\\[\\]_<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.replaceAll("").trim();
    }

    /**
     * 判断表达式为 True
     * @param expression
     * @param errMessage
     */
    public static void isTrue(boolean expression, ErrorCode errMessage,Object... args) {
        if (!expression) {
            throw new I18NException(errMessage,args);
        }
    }

    /**
     * 判断表达式为 True
     * @param expression 表达式
     * @param exception 自定义异常
     * @param <T> 异常类型
     */
    public static<T extends RuntimeException> void isTrue(boolean expression, T exception) {
        if (!expression) {
            throw exception;
        }
    }

    /**
     * 判断对象为非空
     * @param object
     * @param errMessage
     */
    public static void notNull(Object object, String errMessage) {
        if (ObjectUtils.isEmpty(object)) {
            throw new ValidationException(errMessage);
        }
    }

    /**
     * 判断集合非空
     * @param collection
     * @param errMessage
     */
    public static void notEmpty(Collection<?> collection, String errMessage) {
        if (CollectionUtils.isEmpty(collection)) {
            throw new ValidationException(errMessage);
        }
    }

    /**
     * 判断 Map 非空
     * @param map
     * @param errMessage
     */
    public static void notEmpty(Map<?, ?> map, String errMessage) {
        if (MapUtils.isEmpty(map)) {
            throw new ValidationException(errMessage);
        }
    }

    /**
     * 判断 Array 非空
     * @param array
     * @param msg
     */
    public static void notEmpty(Object[] array,String msg){
        if (ArrayUtils.isEmpty(array)) {
            throw new ValidationException(msg);
        }
    }


    /**
     * 校验正则表达式
     * @param regex
     * @param value
     * @return
     */
    public static boolean regex(String regex,String value) {
        Pattern p = Pattern.compile(regex);
        return p.matcher(value).matches();
    }
}
